package com.study.crypto.general.spring.interceptor.mybatis;

import com.study.crypto.general.spring.common.GeneralEntity;
import com.study.crypto.utils.EssPdfUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.BeanWrapperImpl;

import java.time.LocalDateTime;
import java.util.Properties;

/**
 * @author Songjin
 * @since 2022-11-02 17:57
 */
@Slf4j
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
        @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}),
})
public class GeneralEntityInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        SqlCommandType sqlCommandType = ms.getSqlCommandType();
        /*
         * 1.新增时通过拦截器自动给 createTime、updateTime 属性赋值，如果 id 属性为空也进行自动赋值
         * 2.更新时自动给 updateTime 属性赋值
         */
        if (sqlCommandType.equals(SqlCommandType.INSERT)) {
            Object parameter = args[1];
            if (parameter instanceof GeneralEntity) {
                GeneralEntity entity = (GeneralEntity) parameter;
                if (StringUtils.isBlank(entity.getId())) {
                    entity.setId(EssPdfUtil.genRandomUuid());
                }
                entity.setCreateTime(LocalDateTime.now());
                entity.setUpdateTime(entity.getCreateTime());
            } else if (checkSuperClassName(parameter)) {
                // 针对其他工程中的数据库实体类进行id、createTime、updateTime属性赋值
                modifyPropertyForInsert(parameter);
            }
        } else if (sqlCommandType.equals(SqlCommandType.UPDATE)) {
            Object parameter = args[1];
            if (parameter instanceof GeneralEntity) {
                GeneralEntity entity = (GeneralEntity) parameter;
                entity.setUpdateTime(LocalDateTime.now());
            } else if (checkSuperClassName(parameter)) {
                // 针对其他工程中的数据库实体类进行updateTime属性赋值
                modifyPropertyForUpdate(parameter);
            }
        }
        return invocation.proceed();
    }

    private void modifyPropertyForUpdate(Object parameter) {
        BeanWrapperImpl beanWrapper = new BeanWrapperImpl(parameter);
        beanWrapper.setPropertyValue("updateTime", LocalDateTime.now());
    }

    private void modifyPropertyForInsert(Object parameter) {
        BeanWrapperImpl beanWrapper = new BeanWrapperImpl(parameter);
        Object id = beanWrapper.getPropertyValue("id");
        if (id == null || StringUtils.isBlank(id.toString())) {
            beanWrapper.setPropertyValue("id", EssPdfUtil.genRandomUuid());
        }
        LocalDateTime now = LocalDateTime.now();
        beanWrapper.setPropertyValue("createTime", now);
        beanWrapper.setPropertyValue("updateTime", now);
    }

    private boolean checkSuperClassName(Object parameter) {
        String simpleName = parameter.getClass().getSuperclass().getSimpleName();
        return "GeneralEntity".equals(simpleName);
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        log.info("传入自定义属性参数");
    }
}
